"""author: wenyao
   data: 2021/4/30
   project: devopscmdb
"""
#类的定义与使用
#定义
#命名规范：一般首字母都是大写（大驼峰式命名）
#        Person，  GoodInfo
#定义关键字： class
#Python2  == 》 经典类、新式类
#python3  == 》 新式类

#python2显式的继承object的类称之为新式类，反之就是经典类
#python3中默认都是继承object，所以都是新式类
# class Atm(object):
#     pass
#
# class Atm():
#     pass
#
# class Atm:
#     pass
#
# class Atm:
#     #属性
#     money = 50000
#     def get_money(self,getmoney):
#         if getmoney <= self.money:
#            self.money -= getmoney
#         else:
#             print("atm机余额不足")
# #实例化
# atm1 = Atm()
# atm2 = Atm()
#属性访问
# print(atm1.money)
# # atm1.get_money(10000)
# Atm.color = "green"
# print(Atm.money)
# print(atm1.color)
# print(atm2.color)
# atm1.area = "hunan"
# # print(Atm.area)
# print(atm2.area)
# print(atm1.money)
# atm1.money = 120
# print(atm2.money)

##########类空间和实例空间##########
#类创建的时候会生成类空间
#实例化对象会生成实例空间，不同的实例之间，空间独立的
#实例查找属性方法的时候，现在实例空间去查找，找不到就去类空间查找
#类空找不到，就去父类空间找
#为什么实例可以去类找属性？
#创建实例的时候，会有一个类对象指针，通过这个指针实例就可以访问类的属性方法了


################__init__方法
#实例对象的构造方法（初始化方法）
#实例化对象的时候自动调用__init__方法
# class Atm:
#     #属性
#     money = 50000
#     def __init__(self,area):
#         self.area = area
#     def get_money(self,getmoney):
#         if getmoney <= self.money:
#            self.money -= getmoney
#         else:
#             print("atm机余额不足")
#
# atm1 = Atm("gongshang")
# atm2 = Atm("jianshe")
# print(atm1.area)
# print(atm2.area)

###########__new__方法
#创建实例， 一般情况下不需要重写
# class Atm:
#     #属性
#     money = 50000
#     def __init__(self,area):
#         print("this is init method")
#         self.area = area
#
#     def __new__(cls, *args, **kwargs):
#         print("this is new method:",cls)
#         print(args,kwargs)
#         return object.__new__(cls)
#
#     def get_money(self,getmoney):
#         print(self.money)
#         if getmoney <= self.money:
#            #self.money -= getmoney
#            self.money2 = self.money - getmoney
#            print("get money......")
#         else:
#             print("atm机余额不足")
# atm1 = Atm("gongshang")
# atm1.get_money(100)
# print(atm1.money2)
# atm2 = Atm("jianshe")
# print(atm2.money)
# print(atm1.area)
# print(atm2.area)

# class ChinaAtm(Atm):
#     def __init__(self,area):
#         print(" this is ChinaAtm init method")
#         self.area = area
#
#     def __new__(cls, *args, **kwargs):
#         print("new ChinaAtm:",cls)
#         return object.__new__(Atm)
#
# hunan_atm = ChinaAtm("湖南")
# print(hunan_atm.money)
# hunan_atm.get_money(100)
# print(hunan_atm.area)


#总结
#__new__ 是创建实例的方法
#__init__对创建好的实例进行初始化工作的

#__new__方法必须要传入一个参数（cls），代表当前类
#__new__必须返回一个实例化对象
#__init__的self就表示__new__返回的实例，__init__对这个实例进行初始化工作
#子类没有定义__new__，会去找父类的__new__
#新式类才有__new__
#如果实例化对象和本身的class不一致，__init__不会执行

#__new__方法是静态方法
#__init__方法是实例方法

#最好不要重写__new__

class Student:
    school = "Agricultural University"
    def __init__(self, name, age, grade):
        self.name = name
        self.age = age
        self.grade = grade

    def sum_grade(self):
        return sum(self.grade.values())

    def avg_grade(self):
        return self.sum_grade()/len(self.grade.values())

# s1 = Student("lilu", 18, {"suxue":100,"english":50,"yuwen":80})
# s1.hobby = "basketball"
# s1.age = 19
# del s1.age
# print(s1.age)
# s2 = Student("zhangrenjie", 18, {"suxue":90,"english":100,"yuwen":80})
# print(s1.school, s1.name, s1.age, s1.grade)
# print(s1.sum_grade(), s1.avg_grade())
# print(s2.sum_grade(), s2.avg_grade())


#单例模式
#无论实例化多少次，都返回同一个对象实例
#重写__new__
class ATM():
    obj = None
    def __new__(cls,*args,**kwargs):
        if not ATM.obj:
            ATM.obj = object.__new__(cls)
        return ATM.obj

    def __init__(self, money, name, location):
        self.money = money
        self.name = name
        self.location = location

    def add_money(self,money):
        print(f"添加金额：{money}")
        self.money += money

    def take_money(self, money):
        print(f"取出金额: {money}")
        self.money -= money

atm1 = ATM(50000, "长沙银行", "hunan")
atm2 = ATM(50000, "长沙银行", "hunan")
print(id(atm1))
print(id(atm2))


